'''
 * CaRComp Execution Environment
 * 
 * Copyright (C) 2011 Taylor L. Riche
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
'''

import subprocess, shlex, time

KILL_STRING = 'quit'.encode()

class BadCopyException(Exception):
    pass

class FilesNotTheSameException(Exception):
    pass

class AppInterface(object):

    def __init__(self, module, node_name, wait=False, arguments=None):
        self._module = module
        self._node_name = node_name
        self._arguments = arguments
        self._need_to_wait = wait
        
    def launch(self, dir):
        addr = dir.address(self._node_name)
        command_string = ''
        if self._arguments == None:
            command_string = 'ssh {} cd {} && python3.1 -m {} {}'.format(addr, dir.package_root, self._module, self._node_name)
        else:
            command_string = 'ssh {} cd {} && python3.1 -m {} {} {}'.format(addr, dir.package_root, self._module, self._arguments, self._node_name)
        #print('Executing: {}'.format(command_string))
        args = shlex.split(command_string)
        self.process = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)

class System(object):
    '''
    classdocs
    '''


    def __init__(self):
        '''
        Constructor
        '''
        self.app_list = []

    def add_app(self, app):
        self.app_list.append(app)
    
    def add_apps(self, apps):
        self.app_list.extend(apps)
        
    def run(self, dir):
        wait_apps = []
        #print('Launching processes')
        for app in self.app_list:
            if app._need_to_wait:
                wait_apps.append(app)
            else:
                app.launch(dir)
        for app in wait_apps:
            app.launch(dir)
    
    def wait_and_end(self):
        timer_val = 45
        #print('Waiting {!s} seconds for execution'.format(timer_val))
        time.sleep(timer_val)
        status = 0
        #print('Killing processes')
        for app in self.app_list:
            #print('Sending kill to {}'.format(app._node_name))
            out_tuple = app.process.communicate(KILL_STRING)
            #print('Kill of {} successful'.format(app._node_name))
            
        for app in self.app_list:
            status = app.process.wait()
            #print('{0} returned with status {1!s}'.format(app._node_name, status))
        